package com.aabte.nettyleran.netty.privateprotocolstack;

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

import java.util.HashMap;
import java.util.concurrent.TimeUnit;

/**
 * @author Daniel
 * @version 1.0
 * @date 2020/3/15
 */
public class HeartBeatReqHandler extends ChannelHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        NettyMessage message = (NettyMessage) msg;

        if (message.getHeader() != null && message.getHeader().getType() == MessageType.LOGIN_RESP.getValue()) {
            // 握手成功，添加定时任务，定时发送心跳
            ctx.executor().scheduleAtFixedRate(new HeartBeatTask(ctx), 0, 5000, TimeUnit.MILLISECONDS);
        } else if (message.getHeader() != null && message.getHeader().getType() == MessageType.HEARTBEAT_RESP.value()) {
            // 心跳响应
            System.out.println("Client receive server heart beat message: " + message);
        } else {
            ctx.fireChannelRead(msg);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
        ctx.fireExceptionCaught(cause);
    }

    private static class HeartBeatTask implements Runnable {

        private ChannelHandlerContext ctx;

        public HeartBeatTask(ChannelHandlerContext ctx) {
            this.ctx = ctx;
        }

        @Override
        public void run() {
            NettyMessage heatBeatMsg = buildHeatBeatMsg();

            System.out.println("Client send heart beat message to server: " + heatBeatMsg);

            this.ctx.writeAndFlush(heatBeatMsg);
        }

        private NettyMessage buildHeatBeatMsg() {
            Header header = Header.builder()
                    .type(MessageType.HEARTBEAT_REQ.value())
                    .attachment(new HashMap<>(0))
                    .build();

            return NettyMessage.builder()
                    .header(header)
                    .build();
        }
    }
}
